package com.sz.virtualbank.service.loan.impl;

import com.sz.virtualbank.common.exception.BusinessException;
import com.sz.virtualbank.dao.entity.LoanRecord;
import com.sz.virtualbank.dao.entity.LoanRepaymentPlan;
import com.sz.virtualbank.dao.entity.User;
import com.sz.virtualbank.dao.mapper.LoanRecordMapper;
import com.sz.virtualbank.dao.mapper.LoanRepaymentPlanMapper;
import com.sz.virtualbank.dao.mapper.TradeRecordMapper;
import com.sz.virtualbank.dao.mapper.UserMapper;
import com.sz.virtualbank.service.account.AccountService;
import com.sz.virtualbank.service.loan.LoanService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 贷款服务实现类
 * 
 * @author Claude
 */
@Service
@Slf4j
public class LoanServiceImpl implements LoanService {

    @Autowired
    private LoanRecordMapper loanRecordMapper;
    
    @Autowired
    private LoanRepaymentPlanMapper loanRepaymentPlanMapper;
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private TradeRecordMapper tradeRecordMapper;
    
    @Autowired
    private AccountService accountService;
    
    @Autowired
    private LoanRepaymentService loanRepaymentService;
    
    // 贷款基准年利率（实际应用中可能需要根据不同条件计算不同利率）
    private static final BigDecimal BASE_YEARLY_RATE = new BigDecimal("4.35");
    
    // 日期格式化器
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LoanRecord applyLoan(Long userId, BigDecimal amount, Integer loanTerm, String purpose, Integer repaymentMethod) {
        // 参数校验
        if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException("贷款金额必须大于0");
        }
        
        if (loanTerm == null || loanTerm <= 0) {
            throw new BusinessException("贷款期限必须大于0");
        }
        
        if (repaymentMethod == null || repaymentMethod < 1 || repaymentMethod > 3) {
            throw new BusinessException("还款方式不正确");
        }
        
        // 获取用户信息
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 检查是否有正在进行中的贷款
        List<LoanRecord> activeLoans = loanRecordMapper.selectByUserId(userId, 1, 0, 100);
        if (activeLoans != null && !activeLoans.isEmpty()) {
            throw new BusinessException("已有正在进行中的贷款，请结清后再申请");
        }
        
        // 利率计算（实际应用中根据用户信用等级、贷款金额、期限等因素综合计算）
        BigDecimal interestRate = BASE_YEARLY_RATE;
        
        // 创建贷款记录
        LoanRecord loanRecord = new LoanRecord();
        loanRecord.setUserId(userId);
        loanRecord.setLoanNo(generateLoanNo());
        loanRecord.setAmount(amount);
        loanRecord.setInterestRate(interestRate);
        loanRecord.setLoanTerm(loanTerm);
        loanRecord.setPurpose(purpose);
        loanRecord.setStatus(0); // 申请中
        loanRecord.setApplyTime(LocalDateTime.now());
        loanRecord.setRepaymentMethod(repaymentMethod);
        loanRecord.setCreateTime(LocalDateTime.now());
        loanRecord.setUpdateTime(LocalDateTime.now());
        
        // 计算月还款金额（等额本息）
        if (repaymentMethod == 1) {
            BigDecimal monthlyRate = interestRate.divide(new BigDecimal("12"), 8, RoundingMode.HALF_UP)
                    .divide(new BigDecimal("100"), 8, RoundingMode.HALF_UP);
            BigDecimal monthlyPayment = calculateEqualPayment(amount, monthlyRate, loanTerm);
            loanRecord.setMonthlyPayment(monthlyPayment);
        }
        
        // 保存贷款记录
        loanRecordMapper.insert(loanRecord);
        
        return loanRecord;
    }

    @Override
    public Map<String, Object> getLoanList(Long userId, Integer status, Integer page, Integer size) {
        if (page == null || page < 1) {
            page = 1;
        }
        
        if (size == null || size < 1) {
            size = 10;
        }
        
        int offset = (page - 1) * size;
        
        // 查询贷款记录
        List<LoanRecord> records = loanRecordMapper.selectByUserId(userId, status, offset, size);
        
        // 查询总记录数
        int total = loanRecordMapper.countByUserId(userId, status);
        
        // 转换为前端展示所需的数据结构
        List<Map<String, Object>> loanList = new ArrayList<>();
        for (LoanRecord record : records) {
            Map<String, Object> loanMap = new HashMap<>();
            // 复制基本属性
            loanMap.put("id", record.getId());
            loanMap.put("userId", record.getUserId());
            loanMap.put("loanNo", record.getLoanNo());
            loanMap.put("amount", record.getAmount());
            loanMap.put("interestRate", record.getInterestRate());
            loanMap.put("loanTerm", record.getLoanTerm());
            loanMap.put("purpose", record.getPurpose());
            loanMap.put("status", record.getStatus());
            loanMap.put("applyTime", record.getApplyTime());
            loanMap.put("approveTime", record.getApproveTime());
            loanMap.put("repaymentMethod", record.getRepaymentMethod());
            loanMap.put("monthlyPayment", record.getMonthlyPayment());
            
            // 添加额外信息
            if (record.getStatus() == 1) { // 已批准
                // 查询已还期数和剩余本金
                List<LoanRepaymentPlan> plans = loanRepaymentPlanMapper.selectByLoanId(record.getId());
                
                int paidPeriods = 0;
                BigDecimal remainingPrincipal = record.getAmount();
                
                for (LoanRepaymentPlan plan : plans) {
                    if (plan.getStatus() == 1) { // 已还
                        paidPeriods++;
                        remainingPrincipal = remainingPrincipal.subtract(plan.getPrincipal());
                    }
                }
                
                loanMap.put("paidPeriods", paidPeriods);
                loanMap.put("totalPeriods", record.getLoanTerm());
                loanMap.put("remainingPrincipal", remainingPrincipal);
            }
            
            loanList.add(loanMap);
        }
        
        Map<String, Object> result = new HashMap<>();
        result.put("total", total);
        result.put("list", loanList);
        
        return result;
    }

    @Override
    public Map<String, Object> getLoanDetail(Long id, Long userId) {
        LoanRecord loanRecord = loanRecordMapper.selectById(id);
        
        // 验证贷款记录是否存在及归属权
        if (loanRecord == null || !loanRecord.getUserId().equals(userId)) {
            throw new BusinessException("贷款记录不存在或不属于当前用户");
        }
        
        Map<String, Object> result = new HashMap<>();
        result.put("loanRecord", loanRecord);
        
        // 计算总利息和剩余本金
        if (loanRecord.getStatus() == 1) {
            // 获取还款计划
            List<LoanRepaymentPlan> plans = loanRepaymentPlanMapper.selectByLoanId(id);
            
            // 计算总利息
            BigDecimal totalInterest = BigDecimal.ZERO;
            for (LoanRepaymentPlan plan : plans) {
                totalInterest = totalInterest.add(plan.getInterest());
            }
            
            // 计算已还本金和利息
            BigDecimal paidPrincipal = BigDecimal.ZERO;
            BigDecimal paidInterest = BigDecimal.ZERO;
            for (LoanRepaymentPlan plan : plans) {
                if (plan.getStatus() == 1) { // 已还款
                    paidPrincipal = paidPrincipal.add(plan.getPrincipal());
                    paidInterest = paidInterest.add(plan.getInterest());
                }
            }
            
            // 计算剩余本金
            BigDecimal remainingPrincipal = loanRecord.getAmount().subtract(paidPrincipal);
            
            result.put("totalInterest", totalInterest);
            result.put("paidPrincipal", paidPrincipal);
            result.put("paidInterest", paidInterest);
            result.put("remainingPrincipal", remainingPrincipal);
            
            // 计算已还期数
            int paidPeriods = 0;
            for (LoanRepaymentPlan plan : plans) {
                if (plan.getStatus() == 1) {
                    paidPeriods++;
                }
            }
            result.put("paidPeriods", paidPeriods);
            result.put("totalPeriods", loanRecord.getLoanTerm());
            
            // 获取下一期还款计划
            LoanRepaymentPlan nextPlan = null;
            for (LoanRepaymentPlan plan : plans) {
                if (plan.getStatus() == 0 || plan.getStatus() == 2) { // 未还或逾期
                    if (nextPlan == null || plan.getDueDate().isBefore(nextPlan.getDueDate())) {
                        nextPlan = plan;
                    }
                }
            }
            
            if (nextPlan != null) {
                result.put("nextPlan", nextPlan);
            }
        }
        
        return result;
    }

    @Override
    public List<LoanRepaymentPlan> getRepaymentPlan(Long loanId, Long userId) {
        LoanRecord loanRecord = loanRecordMapper.selectById(loanId);
        
        // 验证贷款记录是否存在及归属权
        if (loanRecord == null || !loanRecord.getUserId().equals(userId)) {
            throw new BusinessException("贷款记录不存在或不属于当前用户");
        }
        
        return loanRepaymentPlanMapper.selectByLoanId(loanId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String repayLoan(Long userId, Long loanId, Long repaymentPlanId, BigDecimal amount, String paymentPassword) {
        // 验证支付密码
        if (!accountService.verifyPayPassword(userId, paymentPassword)) {
            throw new BusinessException("支付密码错误");
        }
        
        // 获取贷款记录
        LoanRecord loanRecord = loanRecordMapper.selectById(loanId);
        if (loanRecord == null || !loanRecord.getUserId().equals(userId)) {
            throw new BusinessException("贷款记录不存在或不属于当前用户");
        }
        
        if (loanRecord.getStatus() != 1) {
            throw new BusinessException("贷款状态不正确，无法还款");
        }
        
        // 获取还款计划
        LoanRepaymentPlan repaymentPlan = loanRepaymentPlanMapper.selectById(repaymentPlanId);
        if (repaymentPlan == null || !repaymentPlan.getLoanId().equals(loanId)) {
            throw new BusinessException("还款计划不存在或不属于当前贷款");
        }
        
        if (repaymentPlan.getStatus() != 0 && repaymentPlan.getStatus() != 2) {
            throw new BusinessException("该期已还款，无需重复还款");
        }
        
        // 检查还款金额
        if (amount.compareTo(repaymentPlan.getAmount()) != 0) {
            throw new BusinessException("还款金额不正确，应还" + repaymentPlan.getAmount() + "元");
        }
        
        // 从账户扣款
        String tradeNo = accountService.pay(userId, amount, "LOAN_REPAYMENT", repaymentPlanId);
        
        // 更新还款计划
        loanRepaymentPlanMapper.recordPayment(repaymentPlanId, amount, 1);
        
        // 检查是否所有期数都已还款，如果是则更新贷款状态为已结清
        List<LoanRepaymentPlan> plans = loanRepaymentPlanMapper.selectByLoanId(loanId);
        boolean allPaid = true;
        for (LoanRepaymentPlan plan : plans) {
            if (plan.getStatus() != 1) {
                allPaid = false;
                break;
            }
        }
        
        if (allPaid) {
            loanRecordMapper.updateStatus(loanId, 3); // 已结清
        }
        
        return tradeNo;
    }

    @Override
    public Map<String, Object> calculateEarlyRepayment(Long loanId, Long userId, String repayDate) {
        // 获取贷款记录
        LoanRecord loanRecord = loanRecordMapper.selectById(loanId);
        if (loanRecord == null || !loanRecord.getUserId().equals(userId)) {
            throw new BusinessException("贷款记录不存在或不属于当前用户");
        }
        
        if (loanRecord.getStatus() != 1) {
            throw new BusinessException("贷款状态不正确，无法提前还款");
        }
        
        // 解析还款日期
        LocalDate repaymentDate;
        try {
            repaymentDate = LocalDate.parse(repayDate, DATE_FORMATTER);
        } catch (Exception e) {
            throw new BusinessException("还款日期格式不正确，应为yyyy-MM-dd");
        }
        
        if (repaymentDate.isBefore(LocalDate.now())) {
            throw new BusinessException("还款日期不能早于当前日期");
        }
        
        // 获取还款计划
        List<LoanRepaymentPlan> plans = loanRepaymentPlanMapper.selectByLoanId(loanId);
        
        // 计算剩余本金
        BigDecimal remainingPrincipal = BigDecimal.ZERO;
        for (LoanRepaymentPlan plan : plans) {
            if (plan.getStatus() == 0 || plan.getStatus() == 2) { // 未还或逾期
                remainingPrincipal = remainingPrincipal.add(plan.getPrincipal());
            }
        }
        
        // 计算提前还款手续费（示例：剩余本金的1%）
        BigDecimal feeRate = new BigDecimal("0.01");
        BigDecimal fee = remainingPrincipal.multiply(feeRate).setScale(2, RoundingMode.HALF_UP);
        
        // 计算截止还款日的利息
        BigDecimal monthlyRate = loanRecord.getInterestRate().divide(new BigDecimal("12"), 8, RoundingMode.HALF_UP)
                .divide(new BigDecimal("100"), 8, RoundingMode.HALF_UP);
        
        // 找到最近一期未还的计划
        LoanRepaymentPlan nextPlan = null;
        for (LoanRepaymentPlan plan : plans) {
            if (plan.getStatus() == 0 || plan.getStatus() == 2) {
                if (nextPlan == null || plan.getDueDate().isBefore(nextPlan.getDueDate())) {
                    nextPlan = plan;
                }
            }
        }
        
        // 计算利息（简化计算，实际应用中需要更复杂的计算方法）
        BigDecimal interest = BigDecimal.ZERO;
        if (nextPlan != null) {
            // 天数比例
            LocalDate lastDueDate = nextPlan.getDueDate().minusMonths(1);
            long days = repaymentDate.toEpochDay() - lastDueDate.toEpochDay();
            BigDecimal daysRatio = new BigDecimal(days).divide(new BigDecimal("30"), 8, RoundingMode.HALF_UP);
            
            // 当期利息
            interest = remainingPrincipal.multiply(monthlyRate).multiply(daysRatio).setScale(2, RoundingMode.HALF_UP);
        }
        
        // 总金额
        BigDecimal totalAmount = remainingPrincipal.add(interest).add(fee);
        
        Map<String, Object> result = new HashMap<>();
        result.put("remainingPrincipal", remainingPrincipal);
        result.put("interest", interest);
        result.put("fee", fee);
        result.put("totalAmount", totalAmount);
        result.put("repayDate", repayDate);
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String earlyRepayment(Long userId, Long loanId, BigDecimal amount, String paymentPassword) {
        return loanRepaymentService.earlyRepayment(userId, loanId, amount, paymentPassword);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean approveLoan(Long loanId, boolean approved, String remark) {
        return loanRepaymentService.approveLoan(loanId, approved, remark);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean generateRepaymentPlan(Long loanId) {
        return loanRepaymentService.generateRepaymentPlan(loanId);
    }
    
    /**
     * 计算等额本息月供
     *
     * @param principal 本金
     * @param monthlyRate 月利率
     * @param loanTerm 贷款期限（月）
     * @return 月供金额
     */
    private BigDecimal calculateEqualPayment(BigDecimal principal, BigDecimal monthlyRate, int loanTerm) {
        // 等额本息月供计算公式：本金 × 月利率 × (1+月利率)^期限 / [(1+月利率)^期限 - 1]
        BigDecimal monthlyRatePlus1 = BigDecimal.ONE.add(monthlyRate);
        BigDecimal powValue = monthlyRatePlus1.pow(loanTerm);
        
        BigDecimal numerator = principal.multiply(monthlyRate).multiply(powValue);
        BigDecimal denominator = powValue.subtract(BigDecimal.ONE);
        
        return numerator.divide(denominator, 2, RoundingMode.HALF_UP);
    }
    
    /**
     * 生成贷款编号
     *
     * @return 贷款编号
     */
    private String generateLoanNo() {
        // 格式：L + 时间戳 + 随机数
        return "L" + System.currentTimeMillis() + String.format("%04d", (int) (Math.random() * 10000));
    }
}
